package com.micolor.logr.runtime.joinpoints;

import com.micolor.logr.runtime.annotation.LogComponent;
import com.micolor.logr.runtime.annotation.LogField;
import com.micolor.logr.runtime.component.EnumDataComponent;
import com.micolor.logr.runtime.entity.*;
import com.micolor.logr.runtime.enums.LogRConfigEnum;
import com.micolor.logr.runtime.properties.LogREnumsProperties;
import com.micolor.logr.runtime.util.ClazzAndMapUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationTargetException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @BelongsProject: logr
 * @BelongsPackage: com.micolor.logr.runtime.joinpoints
 * @Author: Evan.Ge
 * @CreateTime: 2024-07-08  21:50
 * @Description: TODO
 * @Version: 1.0
 */
@Component
@Slf4j
public class UpdateJoinPoint {
    @Resource
    EnumDataComponent enumDataComponent;
    @Resource
    private LogREnumsProperties logREnumsProperties;
    public StorageData joinPoint(StorageData storageData,
                                 LogMessage logMessage,
                                 LogComponent logComponent,
                                 List<FieldDetail> logFields,
                                 Object[] paramObject,
                                 Object resultObject)
            throws
            IllegalAccessException,
            ClassNotFoundException,
            InvocationTargetException,
            NoSuchMethodException {

        //paramObject[0]将请求参数从Object类型转换成Map类型
        Map<String, Object> oldValueMap = ClazzAndMapUtil.transObjectToMap(paramObject[0], logComponent.callSuper());
        //paramObject[1] 是用来获得带修改数据信息
        Map<String, Object> paramMap = ClazzAndMapUtil.transObjectToMap(paramObject[1], logComponent.callSuper());
        //将result从Object类型转换成Map类型
        Map<String, Object> resultMap = ClazzAndMapUtil.transObjectToMap(resultObject, logComponent.callSuper());

        List<LogMessageItem> updateMessageItems = new ArrayList<>();
        List<LogMessageItem> paramsMessageItems = new ArrayList<>();
        StringBuilder message = new StringBuilder();
        StringBuilder targets = new StringBuilder();
        Map<String,Object> shardingMap = new HashMap<>();
        for (FieldDetail field : logFields) {
            LogField logField = field.getLogField();

            if (paramMap.get(field.getFieldName()) != null) {
                //处理操作人
                if (logField.isUpdateOperator()) {
                    String updateByName = String.valueOf(paramMap.get(field.getFieldName()));
                    logMessage.setOperator(updateByName);
                    storageData.setOperatorName(logMessage.getOperator());
                }
            }

            //处理完成更新后的数据信息
            if (resultMap.get(field.getFieldName()) != null) {
                LogMessageItem logMessageItem = new LogMessageItem();
                logMessageItem.setName(field.getFieldName());
                logMessageItem.setDesc(logField.value());
                logMessageItem.setOriginalValue(resultMap.get(field.getFieldName()));
                logMessageItem.setTransValue(resultMap.get(field.getFieldName()));

                //开始处理各种注解设定的东西
                //处理enumTrans的标志
                if (!logField.enumTrans().isEmpty()) {
                    String enumTrans = logField.enumTrans();
                    List<LogFieldEnum> logFieldEnums;
                    if (!logField.enumPrecision()) {
                        String enumName = enumTrans.split(":")[0];
                        String enumType = enumTrans.split(":")[1];
                        logFieldEnums = enumDataComponent.getEnumObject(enumName, enumType);
                    } else {
                        logFieldEnums = enumDataComponent.getEnumObject(enumTrans, resultMap);
                    }
                    if (!logFieldEnums.isEmpty()) {
                        logFieldEnums.stream().filter(e -> e.getKey().equals(logMessageItem.getOriginalValue())).
                                findFirst().ifPresent(logFieldEnum ->
                                        logMessageItem.setTransValue(logFieldEnum.getValue() + "[" + logMessageItem.getOriginalValue() + "]"));
                    }
                }

                //处理日期
                if (!logField.dateFormat().isEmpty()) {
                    String regx = logField.dateFormat();
                    Date date = (Date) resultMap.get(field.getFieldName());
                    String dateStr = new SimpleDateFormat(regx).format(date);
                    logMessageItem.setTransValue(dateStr);
                    //新增操作特殊处理
                    //将时间放入到logMessage中
                    logMessage.setTime(dateStr);
                    storageData.setOperateTime(date);
                }

                //是否是业务主键
                if(logField.isBizId()){
                    storageData.setBizId(String.valueOf(resultMap.get(field.getFieldName())));
                }
                //是否是关联对象
                if(logField.isTarget()){
                    targets.append(resultMap.get(field.getFieldName())).append(",");
                }
                //处理分表字段
                if(logField.isShardingField()){
                    shardingMap.put(field.getFieldName(),resultMap.get(field.getFieldName()));
                }
                updateMessageItems.add(logMessageItem);
            }
            //处理更新前的数据信息
            if (oldValueMap.get(field.getFieldName()) != null) {
                LogMessageItem logMessageItem = new LogMessageItem();
                logMessageItem.setName(field.getFieldName());
                logMessageItem.setDesc(logField.value());
                logMessageItem.setOriginalValue(oldValueMap.get(field.getFieldName()));
                logMessageItem.setTransValue(oldValueMap.get(field.getFieldName()));

                //处理enumTrans的标志
                if (!logField.enumTrans().isEmpty()) {
                    String enumTrans = logField.enumTrans();
                    List<LogFieldEnum> logFieldEnums;
                    if (!logField.enumPrecision()) {
                        String enumName = enumTrans.split(":")[0];
                        String enumType = enumTrans.split(":")[1];
                        logFieldEnums = enumDataComponent.getEnumObject(enumName, enumType);
                    } else {
                        logFieldEnums = enumDataComponent.getEnumObject(enumTrans, oldValueMap);
                    }
                    if (!logFieldEnums.isEmpty()) {
                        logFieldEnums.stream().filter(e -> e.getKey().equals(logMessageItem.getOriginalValue())).
                                findFirst().ifPresent(logFieldEnum ->
                                        logMessageItem.setTransValue(logFieldEnum.getValue() + "[" + logMessageItem.getOriginalValue() + "]"));
                    }
                }
                //处理日期
                if (!logField.dateFormat().isEmpty()) {
                    String regx = logField.dateFormat();
                    Date date = (Date) resultMap.get(field.getFieldName());
                    String dateStr = new SimpleDateFormat(regx).format(date);
                    logMessageItem.setTransValue(dateStr);
                    //新增操作特殊处理
                    //将时间放入到logMessage中
                    logMessage.setTime(dateStr);
                }

                //处理操作人
                if (logField.isUpdateOperator()) {
                    String updateByName = String.valueOf(paramMap.get(field.getFieldName()));
                    logMessage.setOperator(updateByName);
                }

                //设置操作人
                if(field.getFieldName().equals("updateBy")){
                    storageData.setOperator(String.valueOf(paramMap.get(field.getFieldName())));
                }
                paramsMessageItems.add(logMessageItem);
            }
        }
        //比较2个对象是否一致
        List<LogMessageChangeItem> logMessageChangeItems = ClazzAndMapUtil.compareList(paramsMessageItems, updateMessageItems);
        if (!logMessageChangeItems.isEmpty()) {
            for (LogMessageChangeItem logMessageChangeItem : logMessageChangeItems) {
                message.append(logMessageChangeItem.getDesc());
                message.append(":");
                message.append("从【");
                message.append(logMessageChangeItem.getTransValue());
                message.append("】修改成【");
                message.append(logMessageChangeItem.getNewTransValue());
                message.append("】，");
            }
        }

        if(!targets.isEmpty()){
            storageData.setTargets(targets.substring(0,targets.length()-1));
        }
        //判断最后记录日志是按何种方式记录的，simple为简单，detail为详细
        //当为simple时，不记录详细信息
        if(logREnumsProperties.getStrategy().equals(LogRConfigEnum.LogR_Strategy_Detail.toString())){
            if (!message.isEmpty()) {
                logMessage.setDetail(message.substring(0, message.length() - 1));
            } else {
                logMessage.setDetail("执行了更新操作，但没有做任何修改。");
            }
        }else{
            logMessage.setDetail("简单记录模式不记录具体信息");
        }
        storageData.setShardingInfo(shardingMap);
        storageData.setMessage(logMessage);
        return storageData;
    }
}
